package org.ewaf.framework.action;

import java.io.IOException;
import java.io.PrintWriter;
import java.text.MessageFormat;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils; //import org.apache.struts2.ServletActionContext;
import org.apache.struts2.interceptor.ParameterAware;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;

//mport com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.interceptor.PreResultListener;
import com.opensymphony.xwork2.util.LocalizedTextUtil;

/**
 * 所有Action的基类
 * 
 * 建议所有result名称与Action方法名称相同或相关，尽量避免重用result名称。
 */
public abstract class BaseAction extends ActionSupport implements
		ServletRequestAware, ServletResponseAware, ParameterAware {

	protected HttpServletResponse httpServletResponse;
	protected HttpServletRequest httpServletRequest;
	protected Map<String, String[]> parameters;

	public void setServletResponse(HttpServletResponse response) {
		this.httpServletResponse = response;
	}

	public void setServletRequest(HttpServletRequest request) {
		this.httpServletRequest = request;
	}

	public void setParameters(Map<String, String[]> parameters) {
		this.parameters = parameters;
	}

	public String[] getParameter(String name) {
		return this.parameters == null ? null : this.parameters.get(name);
	}

	public String getSingleParameter(String name) {
		String[] values = getParameter(name);
		if (values == null || values.length < 1) {
			return null;
		}
		return values[0];
	}

	public String getSingleParameter(String name, String defaultValue) {
		String value = getSingleParameter(name);
		if (value == null) {
			return defaultValue;
		}
		return value;
	}

	public Integer getIntegerParameter(String name, Integer defaultValue) {
		String value = getSingleParameter(name);
		if (StringUtils.isEmpty(value)) {
			return defaultValue;
		}
		return Integer.parseInt(value);
	}
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 2585980576848465121L;
	// 公用result名称
	protected static final String HOME = "home";
	protected static final String TO_URL = "toUrl";
	protected static final String JSON = "json";

	/**
	 * 环境变量，参见spring-framework.xml中env的定义
	 */
	protected Properties env;

	// 由ObjectFactory调用该方法，将Spring容器中的Bean注入Action
	public void setEnv(Properties env) {
		this.env = env;
	}

	public Properties getEnv() {
		return env;
	}

	/**
	 * 执行完Action方法后重定向的URL
	 */
	protected String toUrl;

	public String getToUrl() {
		return toUrl;
	}

	public void setToUrl(String toUrl) {
		this.toUrl = toUrl;
	}

	/**
	 * 重定向时携带的消息（包括actionMessages、actionErrors和fieldErrors）
	 */
	public String getForwardMessage() {
		StringBuffer msg = new StringBuffer();

		for (Iterator<String> i = getActionMessages().iterator(); i.hasNext();) {
			String txt = i.next();
			if (StringUtils.isBlank(txt)) {
				continue;
			}

			if (msg.length() > 0) {
				msg.append('&');
			}

			msg.append("m=");
			msg.append(escape(txt));
		}

		for (Iterator<String> i = getActionErrors().iterator(); i.hasNext();) {
			String txt = (String) i.next();
			if (StringUtils.isBlank(txt)) {
				continue;
			}

			if (msg.length() > 0) {
				msg.append('&');
			}

			msg.append("e=");
			msg.append(escape(txt));
		}

		for (Iterator<Map.Entry<String, List<String>>> i = getFieldErrors()
				.entrySet().iterator(); i.hasNext();) {
			Entry<String, List<String>> e = i.next();

			String fieldName = (String) e.getKey();
			List<String> errorList = e.getValue();

			for (Iterator<String> j = errorList.iterator(); j.hasNext();) {
				String txt = (String) j.next();
				if (StringUtils.isBlank(txt)) {
					continue;
				}

				if (msg.length() > 0) {
					msg.append('&');
				}

				msg.append("f.");
				msg.append(fieldName);
				msg.append('=');
				msg.append(escape(txt));
			}
		}

		return msg.toString();
	}

	public void setForwardMessage(final String forwardMessage) {
		if (StringUtils.isBlank(forwardMessage)) {
			return;
		}

		ActionInvocation invocation = ActionContext.getContext()
				.getActionInvocation();
		invocation.addPreResultListener(new PreResultListener() {

			public void beforeResult(ActionInvocation invocation,
					String resultCode) {
				String[] items = forwardMessage.split("&");
				for (int i = 0; i < items.length; i++) {
					String item = items[i];
					if (StringUtils.isBlank(item)) {
						continue;
					}

					int offset = item.indexOf('=');
					if (offset > 0) {
						String key = item.substring(0, offset);
						String value = item.substring(offset + 1);

						if (StringUtils.isNotBlank(key)
								&& StringUtils.isNotBlank(value)) {
							value = unescape(value);

							if ("m".equals(key)) {
								addActionMessage(value);
							} else if ("e".equals(key)) {
								addActionError(value);
							} else {
								addFieldError(key.substring(2), value);
							}
						}
					}
				}
			}

		});

	}

	private String escape(String txt) {
		txt = txt.replace("%", "%25");
		txt = txt.replace("&", "%26");
		return txt.replace("=", "%3D");
	}

	private String unescape(String txt) {
		txt = txt.replace("%3D", "=");
		txt = txt.replace("%26", "&");
		return txt.replace("%25", "%");
	}

	private String currentUrl;

	public String getCurrentUrl() {
		if (currentUrl == null) {

			StringBuffer url = httpServletRequest.getRequestURL();
			String qs = httpServletRequest.getQueryString();
			if (qs != null) {
				Pattern pattern = Pattern.compile(
						"\\&?forwardMessage\\=[^\\&]*",
						Pattern.CASE_INSENSITIVE);
				Matcher matcher = pattern.matcher(qs);
				if (matcher.find()) {
					StringBuffer sb = new StringBuffer();
					matcher.appendReplacement(sb, "");
					matcher.appendTail(sb);

					if (sb.length() > 0) {
						url.append('?');
						url.append(sb);
					}
				} else {
					url.append('?');
					url.append(qs);
				}
			}

			currentUrl = url.toString();
		}

		return currentUrl;
	}

	protected String getText(Enum<?> errorCode, Object... parameters) {
		ActionContext ctx = ActionContext.getContext();
		String message = LocalizedTextUtil.findText(errorCode.getClass(),
				errorCode.toString(), ctx.getLocale());

		if (parameters != null) {
			return MessageFormat.format(message, parameters);
		} else {
			return message;
		}
	}

	protected String getText(Enum<?> errorCode) {
		return getText(errorCode, (Object[]) null);
	}

	@Deprecated
	protected PrintWriter getPrintWrite() {
		httpServletResponse.setContentType("text/json; charset=UTF-8"); // 处理中文问题的必须的代码
		PrintWriter out = null;
		try {
			out = httpServletResponse.getWriter();
		} catch (IOException e) {
			throw new RuntimeException(e.getMessage(), e);
		}
		return out;
	}

	@Deprecated
	protected PrintWriter grantPrintWrite() {
		httpServletResponse.setContentType("text/plain; charset=UTF-8"); // 处理中文问题的必须的代码
		PrintWriter out = null;
		try {
			out = httpServletResponse.getWriter();
		} catch (IOException e) {
			throw new RuntimeException(e.getMessage(), e);
		}
		return out;
	}
}
